package com.tangsm.spring.boot.async.controller;

import com.tangsm.spring.boot.async.domain.UserInfo;
import com.tangsm.spring.boot.async.service.AsyncCustomService;
import com.tangsm.spring.boot.async.service.AsyncDefaultService;
import com.tangsm.spring.boot.async.service.AsyncMultitaskService;
import com.tangsm.spring.boot.async.task.CustomTaskThread;
import com.tangsm.spring.boot.async.utlis.ListUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;

/**
 * 异步测试控制器
 *
 * @author tangsm
 */
@RestController
public class AsyncController {
    private static final Logger log = LoggerFactory.getLogger(AsyncController.class);

    @Autowired
    private AsyncDefaultService asyncDefaultService;

    @Autowired
    private AsyncCustomService asyncCustomService;

    @Autowired
    private AsyncMultitaskService asyncMultitaskService;

    //@Qualifier
    @Resource(name = "customTaskExecutor")
    private ThreadPoolTaskExecutor customTaskExecutor;

    private static final List<UserInfo> USER_LIST;

    static {
        USER_LIST = new ArrayList<>();
        for (long i = 0; i < 100 ; i++) {
            USER_LIST.add(new UserInfo(i, "小美" + i, "0", 18, new BigDecimal("172")));
        }
    }

    /**
     * 默认async无返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo1")
    public String demo1() {
        log.info("默认async无返回值异步请求开始");
        asyncDefaultService.async();
        log.info("默认async无返回值异步请求结束");
        return "ok";
    }

    /**
     * 默认async有返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo2")
    public String demo2() throws ExecutionException, InterruptedException {
        log.info("默认async有返回值异步请求开始");
        Future<String> future = asyncDefaultService.asyncFuture();
        log.info("默认async有返回值异步请求结束");

        log.info("默认async有返回值异步请求结果：{}", future.get());
        return "ok";
    }

    /**
     * 自定义async无返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo3")
    public String demo3() {
        log.info("自定义async无返回值异步请求开始");
        asyncCustomService.async();
        log.info("自定义async无返回值异步请求完成");
        return "ok";
    }

    /**
     * 自定义async有返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo4")
    public String demo4() throws ExecutionException, InterruptedException {
        log.info("自定义async有返回值异步请求开始");
        Future<String> future = asyncCustomService.asyncFuture();
        log.info("自定义async有返回值异步请求结束");
        log.info("默认async有返回值异步请求结果：{}", future.get());
        return "ok";
    }

    /**
     * 多任务async无返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo5")
    public String demo5() {
        log.info("多任务async无返回值异步请求开始");
        for (int i = 0; i < 100; i++) {
            asyncMultitaskService.async(i);
        }
        log.info("多任务async无返回值异步请求结束");
        return "ok";
    }

    /**
     * 多任务async有返回值异步方法
     *
     * @return 响应结果
     */
    @GetMapping("/demo6")
    public String demo6() {
        log.info("多任务async有返回值异步请求开始");
        List<Future<String>> list = new ArrayList<>(100);
        for (int i = 0; i < 100; i++) {
            list.add(asyncMultitaskService.asyncFuture(i));
        }
        log.info("多任务async有返回值异步请求结束");
        list.forEach(future -> {
            try {
                log.info("多任务async有返回值异步请求结果：{}", future.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return "ok";
    }

    /**
     * ThreadPoolTaskExecutor多线程带返回值异步请求
     *
     * @return 响应结果
     */
    @GetMapping("/demo7")
    public String demo7() {
        // 计算最小线程数
        int count = Math.min(USER_LIST.size(), 5);

        // 根据线程数量拆分数据
        List<List<UserInfo>> splitList = ListUtil.splitByCount(USER_LIST, count);
        // 异步计算结果集合
        List<Future<String>> futureList = new ArrayList<>();

        log.info("ThreadPoolTaskExecutor多线程带返回值异步，请求开始。");
        for (List<UserInfo> userList : splitList) {
            Callable<String> task = new CustomTaskThread(userList);
            // 提交带返回值的线程
            Future<String> future = customTaskExecutor.submit(task);
            futureList.add(future);
        }
        log.info("ThreadPoolTaskExecutor多线程带返回值异步，请求结束。");
        try {
            StringBuilder sb = new StringBuilder();
            // 获取响应结果
            for (Future<String> future : futureList) {
                sb.append(future.get());
            }
            log.info("ThreadPoolTaskExecutor多线程带返回值异步，请求结果：{}", sb);
        } catch (Exception e) {
            log.error("castNew铸造商品定时处理异常", e);
        }
        return "ok";
    }

    /**
     * fork/join多线程带返回值异步请求
     *
     * @return 响应结果
     */
    @GetMapping("/demo8")
    public String demo8() {
        log.info("fork/join多线程带返回值异步，请求开始。");
        // 通过ForkJoin线程池请求处理
        ForkJoinTask<String> customPoolTask = new CustomTaskThread(USER_LIST);
        // 创建主线程为20个forkJoin线程池
        ForkJoinPool pool = new ForkJoinPool(2);
        log.info("fork/join多线程带返回值异步，请求结束。");
        // 获取线程池处理结果（成功总数）
        String result = pool.invoke(customPoolTask);
        log.info("fork/join多线程带返回值异步，请求结果：{}", result);
        //关闭线程池
        pool.shutdown();
        return "ok";
    }
}
